/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

package jchip.backend;
import jchip.backend.replies.*;
import java.util.*;

import java.net.MalformedURLException;
import java.net.URL;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.*;

public class INFLobbyClient {
	protected XmlRpcClient rpcClient;
	protected XmlRpcClientConfigImpl rpcConfig;
	
	private INFLobbyClient() {
	}
	
	public INFLobbyClient(String serviceUrl) throws MalformedURLException {
		this.rpcConfig = new XmlRpcClientConfigImpl();
		this.rpcConfig.setServerURL(new URL(serviceUrl));
		this.rpcConfig.setEnabledForExtensions(true);
		this.rpcConfig.setGzipRequesting(true);
	    
		this.rpcClient = new XmlRpcClient();
		this.rpcClient.setConfig(this.rpcConfig);
	}
	
	public void setServiceUrl(String serviceUrl)  throws MalformedURLException {
		this.rpcConfig.setServerURL(new URL(serviceUrl));
	}
	public INFLobbyPollTimings getPollTimings() {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.getPollTimings", new Object[0]);
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		Map resultMap = (Map)result;
		
		INFLobbyPollTimings timings = new INFLobbyPollTimings();
		timings.waiting = ((Integer)resultMap.get("waiting")).intValue();
		timings.playing = ((Integer)resultMap.get("playing")).intValue();
		
		return timings;
	}
	public INFLobbyChallenge getChallenge() {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.getChallenge", new Object[0]);
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		Map challengeMap = (Map)result;
		INFLobbyChallenge out = new INFLobbyChallenge(); 
		
		out.challengeId = (Integer)challengeMap.get("challengeid");
		out.mimeType = (String)challengeMap.get("mimetype");
		out.challengeData = (byte[])challengeMap.get("content");

		return out;
	}
	
	public int getSessionId(int challengeId, String challengeReply) {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.getSessionId", new Object[]{new Integer(challengeId), challengeReply});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		return ((Integer)result).intValue();
	}
	
	public boolean setNickname(int sessionId, String nickname) {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.setNickname", new Object[]{new Integer(sessionId), nickname});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		return ((Boolean)result).booleanValue();
	}
	
	public INFLobbyQueueInfo[] getQueues(int sessionId) {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.getQueues", new Object[]{new Integer(sessionId)});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		Object queueinfoObjects[] = (Object[])result;
		Map queueinfoMaps[] = new Map[queueinfoObjects.length];
		for (int i = 0; i < queueinfoMaps.length; i++) {
			queueinfoMaps[i] = (Map)queueinfoObjects[i];
		}
		
		INFLobbyQueueInfo queueInfos[] = new INFLobbyQueueInfo[queueinfoMaps.length];		
		for (int i = 0; i < queueinfoMaps.length; i++) {
			queueInfos[i] = new INFLobbyQueueInfo();
			queueInfos[i].queueid = ((Integer)queueinfoMaps[i].get("queueid")).intValue();
			queueInfos[i].count = ((Integer)queueinfoMaps[i].get("count")).intValue();
			queueInfos[i].title = (String)queueinfoMaps[i].get("title");
			queueInfos[i].ip = (String)queueinfoMaps[i].get("ip");
			queueInfos[i].port = (String)queueinfoMaps[i].get("port");
			queueInfos[i].description = (String)queueinfoMaps[i].get("description");
		}
		
		return queueInfos;
	}
	
	public boolean setQueues(int sessionId, int queueIds[]) {
		Integer queueIdsInt[] = new Integer[queueIds.length];
		for (int i = 0; i < queueIds.length; i++) {
			queueIdsInt[i] = new Integer(queueIds[i]);
		}
		
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.setQueues", new Object[]{new Integer(sessionId), queueIdsInt});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		return ((Boolean)result).booleanValue();
	}
	
	public boolean setStatus(int sessionId, int status) {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.setStatus", new Object[]{new Integer(sessionId), new Integer(status)});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		return ((Boolean)result).booleanValue();
	}
	
	public INFLobbyPollInfo pollUpdates(int sessionId) {
		//execute XMLRPC Call
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.pollUpdates", new Object[]{new Integer(sessionId)});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		//Type Conversion
		
		//extract queues and users
		Map resultMap = (Map)result;
		Map queuesMap = (Map)resultMap.get("queues");
		Object usersObj[] = (Object[])resultMap.get("users");
		
		//first process the queues
		
		//theses are the updated lists the client has to apply to it's saved lists
		INFLobbyQueueUpdate queueUpdates[]=null;
		
		if(queuesMap!=null) {
			queueUpdates = new INFLobbyQueueUpdate[queuesMap.size()];
			int queueId=0;
			int i=0;
			Iterator it = queuesMap.keySet().iterator();
			while(it.hasNext())
			{
				queueId = Integer.parseInt((String)it.next());
				//the userids list for the specific queue in its untyped xmlrpc form
				Object userIdObjs[] = (Object[])queuesMap.get(String.valueOf(queueId));
				
				queueUpdates[i] = new INFLobbyQueueUpdate();
				queueUpdates[i].queueid = queueId;
				queueUpdates[i].userids = new int[userIdObjs.length]; 
				
				//fille userid list of queue update
				for (int k = 0; k < userIdObjs.length; k++) {
					queueUpdates[i].userids[k] = ((Integer)userIdObjs[k]).intValue();
				}
				i++;
			}
		}
		
		//second process users
		
		INFLobbyUserInfo userInfos[] = new INFLobbyUserInfo[usersObj.length];
		
		for (int i = 0; i < usersObj.length; i++) {
			Map userMap = (Map)usersObj[i];
			userInfos[i] = new INFLobbyUserInfo();
			
			userInfos[i].userid = ((Integer)userMap.get("userid")).intValue();
			userInfos[i].nick = (String)userMap.get("nick");
			userInfos[i].status = ((Integer)userMap.get("status")).intValue();
		}
		
		//construct final pollinfo Object
		INFLobbyPollInfo out = new INFLobbyPollInfo();
		out.queues = queueUpdates;
		out.users = userInfos;
		
		return out;
	}
	
	public boolean pollKeepAlive(int sessionId) {
		Object result=null;
		try {
			result = this.rpcClient.execute("INFLobby.pollKeepAlive", new Object[]{new Integer(sessionId)});
		} catch (XmlRpcException e) {
			e.printStackTrace();
		}
		
		return ((Boolean)result).booleanValue();
	}
}
